package saas.dev.cloud.filter;

import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import saas.dev.cloud.config.IgnoreProperties;
import saas.dev.cloud.util.RedisUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName : GlobalFilter
 * @Author : y1
 * @Date: 2022/5/18 15:14
 * @Description :
 */
@Slf4j
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private IgnoreProperties ignoreProperties;

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //　如果在忽略的url里，则跳过
        String path = replacePrefix(request.getURI().getPath());
        String requestUrl = request.getURI().getRawPath();
        if (ignore(path)) {
            return chain.filter(exchange);
        }

        String token = request.getHeaders().getFirst("token");
        if (token == null) {
            throw new RuntimeException("未登陆");
        }
        String role = redisUtils.get(token);
        if (Validator.isNull(role)) {
            throw new RuntimeException("登陆已过期");
        }
        if (JSON.parseArray(role,String.class).stream()
                .map(url -> url.replace("/**", "")).noneMatch(path::startsWith)) {
            throw new RuntimeException("未授权，无法访问");
        }
        return chain.filter(exchange);
    }

    /**
     * 移除模块前缀
     *
     * @param path 路径
     * @return String
     */
    private String replacePrefix(String path) {
        if (path.startsWith("/auth") || path.startsWith("/user")) {
            log.info(path.replace("/**", ""));
            return path.substring(path.indexOf("/", 1));
        }
        return path;
    }

    /**
     * 检查是否忽略url
     *
     * @param path 路径
     * @return boolean
     */
    private boolean ignore(String path) {
        return ignoreProperties.getIgnoreUrl().stream()
                .map(url -> url.replace("/**", "")).anyMatch(path::startsWith);
    }

}
